#include "ScriptEngine.h"
#include <Core/Inputs.h>
#include <Core/Uuid.h>
#include <ScriptEngine/ScriptType.h>
#include <GameObject/Components.h>
#include <GameObject/Scene.h>
#include <GameObject/Object.h>


namespace Engine2D
{    
    ScriptEngine & ScriptEngine::Instance()
    {
        static ScriptEngine instance;
        return instance;
    }

    void ScriptEngine::Script(const std::string &src)
    {
        try {
            s_lua.script(src);
        }
        catch(const std::exception& e) {
            if (m_scriptErrorCb) {
                m_scriptErrorCb(e.what());
            }
            LOG_ERROR("{}", e.what());
        }
    }

    ScriptEngine::ScriptEngine()
    {
        s_lua.open_libraries();
        s_lua.script("print(\"Lua Init\")");
    }

    
    Uuid GetMainCameraUuid() 
    {
        if (!Renderer::Instance()->MainCamera()) {
            throw std::runtime_error("Camera is not exist!");
        }
        return Renderer::Instance()->MainCamera()->GetComponent<IDComponent>().lock()->uuid;
    }    

    Uuid GetUuid(const std::string & uuidStr) {
        return Uuid(uuidStr);
    }

    TransformComponent & GetTransformComponent(Uuid uuid)
    {
        if (!ScriptEngine::ScriptEngine::Instance().ActiveScene()) {
            throw std::runtime_error("No scene active!");
        }
        auto obj = ScriptEngine::ScriptEngine::Instance().ActiveScene()->GetObjectByUuid(uuid);
        if (!obj) {
            throw std::runtime_error("Can not find object by id: " + uuid());
        }
        if (obj->GetComponent<TransformComponent>().expired()) {
            throw std::runtime_error("Can not find TransformComponent!");
        }
        return *obj->GetComponent<TransformComponent>().lock();
    }



    int ScriptEngineInit = ([](){ 
        ScriptEngine::Instance().State().set_function("IsKeyDown", &Inputs::IsKeyDown);
        ScriptEngine::Instance().State().set_function("IsKeyPressed", &Inputs::IsKeyPressed);
        ScriptEngine::Instance().State().set_function("IsKeyReleased", &Inputs::IsKeyReleased);
        ScriptEngine::Instance().State().set_function("MouseXPos", &Inputs::MouseXPos);
        ScriptEngine::Instance().State().set_function("MouseYPos", &Inputs::MouseYPos);
        ScriptEngine::Instance().State().set_function("MouseWheelH", &Inputs::MouseWheelH);
        ScriptEngine::Instance().State().set_function("IsMouseDown", &Inputs::IsMouseDown);
        ScriptEngine::Instance().State().set_function("IsMouseClicked", &Inputs::IsMouseClicked);
        ScriptEngine::Instance().State().set_function("IsMouseReleased", &Inputs::IsMouseReleased);

        ScriptEngine::RegisterUserType<Uuid>();
        ScriptEngine::Instance().State().set_function("GetUuid", GetUuid);


        ScriptEngine::RegisterUserType<SLua_Vec2>();
        ScriptEngine::RegisterUserType<SLua_Vec3>();
        ScriptEngine::RegisterUserType<SLua_Vec4>();

        ScriptEngine::RegisterUserType<TransformComponent>();

        ScriptEngine::Instance().State().set_function("GetMainCamera", GetMainCameraUuid);
        ScriptEngine::Instance().State().set_function("GetTransformComponent", GetTransformComponent);


    }(), 0);

} // namespace Engin2D


